package com.movie.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import static org.springframework.security.config.Customizer.withDefaults;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {

    @Autowired
    private JwtRequestFilter jwtRequestFilter;

    // 定义密码编码器 Bean - 使用简单的明文编码器
    @Bean
    public PasswordEncoder passwordEncoder() {
        // 不进行任何加密，直接返回明文
        return new PasswordEncoder() {
            @Override
            public String encode(CharSequence rawPassword) {
                return rawPassword.toString();
            }

            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                return rawPassword.toString().equals(encodedPassword);
            }
        };
    }

    // 暴露 AuthenticationManager Bean
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            // 禁用 CSRF，因为我们使用 JWT，不需要 session
            .csrf(csrf -> csrf.disable())
            // 配置请求授权规则
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/auth/register", "/api/auth/login").permitAll()
                .requestMatchers("/api/movies/**").permitAll()
                .requestMatchers("/api/showtimes/**").permitAll()
                .requestMatchers("/api/seats/**").permitAll()
                .requestMatchers("/api/orders").permitAll()
                // 用户个人信息接口需要认证
                .requestMatchers("/api/users/profile").authenticated()
                .requestMatchers("/api/users/profile/**").authenticated()
                // 允许用户访问统计数据接口
                .requestMatchers("/api/users/stats/**").authenticated()
                // 管理员特定接口
                .requestMatchers("/api/admin/**").hasRole("ADMIN")
                // 允许用户访问余额相关接口
                .requestMatchers("/api/users/balance/**").authenticated()
                // 管理后台其他资源，需要 ADMIN 角色
                .requestMatchers("/api/users/**").hasRole("ADMIN")
                // !!! 移除或修改过于宽泛的订单规则 !!!
                // .requestMatchers("/api/orders/**").hasRole("ADMIN")
                // 让 anyRequest().authenticated() 捕获订单路径，由 @PreAuthorize 控制具体权限
                .requestMatchers("/api/reviews/**").hasRole("ADMIN")
                .requestMatchers("/api/statistics/**").hasRole("ADMIN")
                // 其他所有请求都需要认证 (例如普通用户访问自己的订单等)
                .anyRequest().authenticated()
            )
            // 配置 Session 管理策略为无状态 (Stateless)，因为我们将使用 JWT
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
            // .httpBasic(withDefaults()); // 可以暂时用 HTTP Basic 测试，后续替换为 JWT

        // 将 JWT 过滤器添加到过滤器链中，在 UsernamePasswordAuthenticationFilter 之前执行
        http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

    // TODO: 配置 UserDetailsService (后续步骤)
    // TODO: 配置 AuthenticationManager (用于登录认证，后续步骤)

}